using System;
using System.Collections;
using System.Xml;
using DesignByContract;
using Outcoding.GraphGenerator.Entities;
using Outcoding.GraphGenerator.Util.Logging;

namespace Outcoding.GraphGenerator.Composition{
    //Recibe el nodo padre del cual seleccionara todos los shape
    public class ShapeBuilder : BuilderBase{
        #region Attributes

        private string indexAttr = "index";

        #endregion

        private readonly string mNodeName = XmlTagNames.shape.ToString();

        private XmlNodeList mNodeList;

        private string mNodePath{
            get { return "./" + mNodeName; }
        }

        public override void SelectNode(XmlDocument document){
            throw new Exception("The method or operation is not implemented.");
        }

        public override void Compose(){
            try{
                BuildObject(mNodeList);
            }
            catch (PreconditionException preExc){
                LogManager.Instance.LogWarning("Shape entity could not be created; process aborted.", preExc);
            }
        }

        public override void Compose(XmlNode node){
            mNodeList = node.SelectNodes(mNodePath);
            if (mNodeList != null){
                try{
                    BuildObject(mNodeList);
                }
                catch (PreconditionException preExc){
                    LogManager.Instance.LogWarning("Shape entity could not be created; process aborted.", preExc);
                }
            }
        }

        public override void AppendToParent(object parent){
            var slide = (Slide) parent;

            var shapeList = (ArrayList) mProduct;
            foreach (Shape tmpShape in shapeList)
                slide.Shapes.Add(tmpShape);
        }

        private void BuildObject(XmlNodeList shapeXmlNodeList){
            var shapeList = new ArrayList();
            foreach (XmlNode node in shapeXmlNodeList){
                var shape = new Shape();
                try{
                    if (node.Attributes[indexAttr] != null)
                        shape.Index = ParseIndexAttribute(node);
                    else
                        shape.Index = Int32.MinValue; //used to distinguish a valid index
                }
                catch (PreconditionException preExc){
                    //log error
                    shape = null;
                    throw;
                }
                if (shape != null)
                    shapeList.Add(shape);
            }

            mProduct = shapeList;
        }

        private int ParseIndexAttribute(XmlNode shapeXmlNode){
            Check.Require(shapeXmlNode.Attributes[indexAttr] != null, "index attribute not present");
            return Int32.Parse(shapeXmlNode.Attributes[indexAttr].Value);
        }
    }
}